// @Title  modbus_tcp.go
// @Description  使用modbusTCP进行数据采集
// @Author  IT搬运工
// @Update
package gather

import (
	"intelligentgateway/src/container"
	"intelligentgateway/src/server"
	"time"

	"github.com/goburrow/serial"
	"github.com/things-go/go-modbus"
)

// @title    CreateRTUClient
// @description   创建modbus RTU客户端
// @auth      IT搬运工             时间（2022/7/14）
// @param
// @return
func CreateRTUClient(addr string, baudRate uint32, dataBits uint8, stopBits uint8, parity string) modbus.Client {
	p := modbus.NewRTUClientProvider(
		modbus.WithSerialConfig(serial.Config{
			Address:  addr,
			BaudRate: int(baudRate),
			DataBits: int(dataBits),
			StopBits: int(stopBits),
			Parity:   parity,
			Timeout:  modbus.SerialDefaultTimeout,
		}))

	client := modbus.NewClient(p)
	err := client.Connect()
	if err != nil {
		timer := time.NewTimer(10 * time.Minute)
		for range timer.C {
			client := modbus.NewClient(p)
			err := client.Connect()
			if err == nil {
				//连接正常
				timer.Stop()
				return client
			}
		}
	}
	return client
}

type RTUCollectInfo struct {
	Addr      string
	BaudRate  uint32
	DataBits  uint8
	StopBits  uint8
	Parity    string
	Sn        string
	ChannelId string
}

//开始启动RTU采集
func startProtobuffRTUCollect(collect *RTUCollectInfo) {
	//启动modbus TCP
	client := CreateRTUClient(collect.Addr, collect.BaudRate,
		collect.DataBits, collect.StopBits, collect.Parity)

	//获取设备的modbus点表
	var pointItemMap = make(map[int]*server.ModbusPoint)
	itemList := server.GetDataTypeBySn(collect.Sn)
	if itemList == nil {
		client.Close()
		return
	}
	for _, mdp := range itemList {
		modbusPoint := server.GetPointsBySn(collect.Sn, mdp.DataType)
		if nil != modbusPoint {
			pointItemMap[mdp.DataType] = modbusPoint
		}
	}

	//没有配置点表
	if len(pointItemMap) == 0 {
		client.Close()
		return
	}

	//获取通道
	channel := container.GetDevChannel(collect.ChannelId)
	if nil == channel {
		//通道未开启，不进行采集
		client.Close()
		return
	}

	//发送A-BMS和堆HVM
	go SendABMSAndHVMData(pointItemMap[int(ABMS)], pointItemMap[int(ABMS)], client, channel, collect.ChannelId, collect.Sn)
}
